;
(function($) {
    $.fn.jHTMLColors = function(options) {
        var _this = this;
        var defaults = {
            type: "safe",
            colors: ['#00ffff', '#000000', '#0000ff', '#ff00ff', '#808080', '#008000', '#00ff00', '#800000', '#000080', '#808000', '#800080', '#ff0000', '#c0c0c0', '#008080', '#ffffff', '#ffff00'],
            mouseclick: function(event, rgb, hex, _this) {},
            mouseenter: function(event, rgb, hex, _this) {},
            mouseleave: function(event, rgb, hex, _this) {}
        };
        $.extend(true, defaults, options);
        _this.addClass("jHTMLColors");
        switch(defaults.type) {
            case "safe": {
                drawSafe(_this, defaults);
                break;
            }
            case "html": {
                drawHTML(_this, defaults);
                break;
            }
            case "gray": {
                drawGray(_this, defaults);
                break;    
            }
        }
    }
    
    function RGBtoHex(r,g,b) {
        return (toHex(r) + toHex(g) + toHex(b));
    }
    
    function toHex(n) {
        if (n == null) {
            return "00";
        }
        n = parseInt(n); 
        if (n == 0 || isNaN(n)) {
            return "00";
        }
        n = Math.max(0, n);
        n = Math.min(n, 255);
        n = Math.round(n);
        return "0123456789ABCDEF".charAt((n - n % 16) / 16) + "0123456789ABCDEF".charAt(n % 16);
    }
    
    function isDark(r, g, b) {
        if (0.299 * r + 0.587 * g + 0.114 * b > 127.5) {
            return false;
        } else {
            return true;
        }
    }
    
    function drawSafe(_this, defaults) {
        for (var r = 0; r <= 256; r += 51) {
            for (var g = 0; g <= 256; g += 51) {
                for (var b = 0; b <= 256; b += 51) {
                    var hex = "#" + RGBtoHex(r, g, b);
                    (function(r, g, b, hex) {
                        $("<div>").html("&nbsp;")
                        .css("background-color", hex)
                        .bind("click", function(event) {
                            defaults.mouseclick(event, "rgb(" + r + "," + g + "," + b + ")", hex, _this);
                        })
                        .bind('mouseenter', function(event) {
                            defaults.mouseenter(event, "rgb(" + r + "," + g + "," + b + ")", hex, _this);
                            mouseenter(event, "rgb(" + r + "," + g + "," + b + ")", hex, _this);
                        })
                        .bind('mouseleave', function(event) {
                            defaults.mouseleave(event, "rgb(" + r + "," + g + "," + b + ")", hex, _this);
                            mouseleave(event, "rgb(" + r + "," + g + "," + b + ")", hex, _this);
                        })
                        .appendTo(_this);
                    })(r, g, b, hex);
                }
            }
        }
    }
    
    function drawHTML(_this, defaults) {
        for (var i in defaults.colors) {
            var hex;
            var rgb;
            var color;
            if (defaults.colors[i].substring(0, 1) == "#") {
                hex = defaults.colors[i];
                color = defaults.colors[i].substring(1, 7);
                rgb = "rgb(" + parseInt(color.substring(0, 2), 16) + "," + parseInt(color.substring(2, 4), 16) + "," + parseInt(color.substring(4, 6), 16) + ")";
            } else {
                color = defaults.colors[i].replace(/\s/g,"");
                var splitRGB = color.match(/^rgb\((\d{1,3}?),(\d{1,3}?),(\d{1,3}?)\)$/i);
                rgb = splitRGB[0];
                hex = "#" + RGBtoHex(splitRGB[1], splitRGB[2], splitRGB[3]);
            }
            (function(rgb, hex) {
                $("<div>").html("&nbsp;")
                .css("background-color", defaults.colors[i])
                .bind("click", function(event) {
                    defaults.mouseclick(event, rgb, hex, _this);
                })
                .bind('mouseenter', function(event) {
                    defaults.mouseenter(event, rgb, hex, _this);
                    mouseenter(event, rgb, hex, _this);
                })
                .bind('mouseleave', function(event) {
                    defaults.mouseleave(event, rgb, hex, _this);
                    mouseleave(event, rgb, hex, _this);
                })
                .appendTo(_this);
            })(rgb, hex);
        }
    }
    
    function drawGray(_this, defaults) {
        for (var g = 0; g <= 256; g += 8) {
            var hex = "#" + RGBtoHex(g, g, g);
            (function(g, hex) {
                $("<div>").html("&nbsp;")
                .css("background-color", hex)
                .bind("click", function(event) {
                    defaults.mouseclick(event, "rgb(" + g + "," + g + "," + g + ")", hex, _this);
                })
                .bind('mouseenter', function(event) {
                    defaults.mouseenter(event, "rgb(" + g + "," + g + "," + g + ")", hex, _this);
                    mouseenter(event, "rgb(" + g + "," + g + "," + g + ")", hex, _this)
                })
                .bind('mouseleave', function(event) {
                    defaults.mouseleave(event, "rgb(" + g + "," + g + "," + g + ")", hex, _this);
                    mouseleave(event, "rgb(" + g + "," + g + "," + g + ")", hex, _this)
                })
                .appendTo(_this);
            })(g, hex);
        }
    }
  
    function mouseenter(event, rgb, hex, _this) {
        rgb = rgb.substring(5, rgb.length - 1);
        var rgbArr = rgb.split(',')
        if (isDark(rgbArr[0], rgbArr[1], rgbArr[2])) {
            $("<div>").text(hex).css("background-color", hex).css('color', 'white').addClass("colorPrev").appendTo(_this);
        } else {
            $("<div>").text(hex).css("background-color", hex).css('color', 'black').addClass("colorPrev").appendTo(_this);
        }
    }

    function mouseleave(event, rgb, hex, _this) {
        $(_this).children(".colorPrev").remove();
    }
})(jQuery);

